package cn.tannn.ops.util;

import cn.tannn.jdevelops.exception.built.BusinessException;
import cn.tannn.ops.common.constant.CloudEnums;
import cn.tannn.ops.nginx.controller.vo.DnsDomain;
import cn.tannn.ops.nginx.controller.vo.DnsDomainRecord;
import cn.tannn.ops.nginx.entity.CloudAccessKey;
import com.aliyun.sdk.service.alidns20150109.AsyncClient;
import com.aliyun.sdk.service.alidns20150109.models.*;
import com.huaweicloud.sdk.dns.v2.DnsClient;
import com.huaweicloud.sdk.dns.v2.model.*;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.shredzone.acme4j.Authorization;
import org.shredzone.acme4j.challenge.Dns01Challenge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * dns util
 *
 * @author <a href="https://t.tannn.cn/">tan</a>
 * @version V1.0
 * @date 2024/8/29 下午12:21
 */
public class DnsUtil {

    private static final Logger LOG = LoggerFactory.getLogger(DnsUtil.class);

    String recordId;
    AsyncClient client;
    DnsClient haWeiClient;
    CreateRecordSetResponse huaweiCreateRecord;

    /**
     * 添加域名TXT解析记录 - ssl证书转专用
     * <code>
     * <p> DomainExtractor.DomainInfo domainInfo = DomainExtractor.extractDomainInfo(domainName);
     * <p> String rr = Dns01Challenge.toRRName(auth.getIdentifier()).replace("." + domainInfo.mainDomain + ".", "");
     * <p> String domainName = domainInfo.mainDomain;
     * </code>
     *
     * @param domainName 域名
     * @param auth,      {@link Authorization} to perform
     * @param value      记录值
     * @param cloud      域名所属的云厂商信息
     */
    @SneakyThrows
    public void addDomainRecord_SSL(String domainName, Authorization auth, String value, CloudAccessKey cloud) {
        if (cloud.getCloud() == CloudEnums.ALI) {
            this.client = AliDnsUtil.init(cloud);
            DomainExtractor.DomainInfo domainInfo = DomainExtractor.extractDomainInfo(domainName);
            String rr = Dns01Challenge.toRRName(auth.getIdentifier()).replace("." + domainInfo.mainDomain + ".", "");
            String existRecordId = AliDnsUtil.getRecordIdByDomain(client, domainInfo.mainDomain, rr, "TXT", value);
            if (StringUtils.isNotBlank(existRecordId)) {
                this.recordId = existRecordId;
                deleteDomainRecord();
                this.client = AliDnsUtil.init(cloud);
            }
            AddDomainRecordResponse domainRecordResponse = AliDnsUtil.addDomainRecord(client
                    , domainInfo.mainDomain
                    , rr
                    , "TXT"
                    , value);
            if (domainRecordResponse != null) {
                recordId = domainRecordResponse.getBody().getRecordId();
            }
        } else if (cloud.getCloud() == CloudEnums.HUAWEI) {
            this.haWeiClient = HwDnsUtil.init(cloud);
//            String domain = Dns01Challenge.toRRName(auth.getIdentifier()).replace("." + domainName, "");
            String domain = Dns01Challenge.toRRName(auth.getIdentifier());
            CreateRecordSetResponse huaweiCreateRecordC = HwDnsUtil.addDomainRecord(haWeiClient
                    , domain
                    , "TXT"
                    , value);
            if (huaweiCreateRecordC != null) {
                this.huaweiCreateRecord = huaweiCreateRecordC;
            }
        } else {
            throw new BusinessException("暂不支持云厂商" + cloud.getCloud().getName());
        }
    }

    /**
     * 删除域名解析记录 - 必须要调用上面 addDomainRecord 之后调用
     */
    public void deleteDomainRecord() {
        try {
            deleteDomainRecord(client, recordId);
            deleteDomainRecord(haWeiClient, huaweiCreateRecord);
        } catch (Exception e) {
            LOG.error("Failed to remove TXT record: " + e.getMessage(), e);
        } finally {
            client = null;
            recordId = null;
            haWeiClient = null;
            huaweiCreateRecord = null;
        }
    }

    /**
     * 删除域名解析记录 - 阿里云
     */
    public static void deleteDomainRecord(AsyncClient client, String recordId) {
        try {
            if (client != null && recordId != null) {
                AliDnsUtil.deleteDomainRecord(client, recordId);
            }
        } catch (Exception e) {
            LOG.error("Failed to remove TXT record: " + e.getMessage(), e);
        }
    }

    /**
     * 删除域名解析记录 - 华为云
     */
    public static void deleteDomainRecord(DnsClient haWeiClient, CreateRecordSetResponse huaweiCreateRecord) {
        try {
            if (haWeiClient != null && huaweiCreateRecord != null) {
                HwDnsUtil.deleteDomainRecord(haWeiClient, huaweiCreateRecord);
            }
        } catch (Exception e) {
            LOG.error("{} Failed to remove TXT record: {}", huaweiCreateRecord.getName(), e.getMessage(), e);
        }
    }

    /**
     * 删除域名解析记录 - 华为云
     */
    public static void deleteDomainRecord(DnsClient haWeiClient, String recordId, String zoneId) {
        try {
            if (haWeiClient != null && zoneId != null) {
                HwDnsUtil.deleteDomainRecord(haWeiClient, recordId, zoneId);
            }
        } catch (Exception e) {
            LOG.error("Failed to remove TXT record: " + e.getMessage(), e);
        }
    }

    /**
     * 查询拥有域名的解析记录
     *
     * @return
     */
    public static List<DnsDomainRecord> findDomainsRecord(CloudAccessKey cloud, DnsDomain domain) {
        List<DnsDomainRecord> resp = new ArrayList<>();
        if (cloud.getCloud() == CloudEnums.ALI) {
            AsyncClient ali = AliDnsUtil.init(cloud);
            DescribeDomainRecordsResponse response = AliDnsUtil.describeDomainRecords(ali, domain.getDomain());
            List<DescribeDomainRecordsResponseBody.Record> records = response.getBody().getDomainRecords().getRecord();
            records.forEach(rc -> resp.add(DnsDomainRecord.toDnsDomainRecord(rc)));
        } else if (cloud.getCloud() == CloudEnums.HUAWEI) {
            DnsClient hw = HwDnsUtil.init(cloud);
            ShowRecordSetByZoneResponse response = HwDnsUtil.showRecordSetByZone(hw, domain);
            List<ShowRecordSetByZoneResp> recordsets = response.getRecordsets();
            recordsets.forEach(rc -> resp.add(DnsDomainRecord.toDnsDomainRecord(rc, domain.getDomain())));
        } else {
            throw new BusinessException("暂不支持云厂商" + cloud.getCloud().getName());
        }
        return resp;
    }

    /**
     * 查询拥有的域名
     *
     * @return
     */
    public static List<DnsDomain> findDomains(CloudAccessKey cloud) {
        List<DnsDomain> resp = new ArrayList<>();
        if (cloud.getCloud() == CloudEnums.ALI) {
            AsyncClient ali = AliDnsUtil.init(cloud);
            DescribeDomainsResponse describeDomains = AliDnsUtil.describeDomains(ali);
            List<DescribeDomainsResponseBody.Domain> domains = describeDomains.getBody().getDomains().getDomain();
            domains.forEach(domain -> {
                resp.add(DnsDomain.builder()
                        .cloud(CloudEnums.ALI)
                        .domain(domain.getDomainName())
                        .domainId(domain.getDomainId())
                        .recordCount(domain.getRecordCount())
                        .build());
            });

        } else if (cloud.getCloud() == CloudEnums.HUAWEI) {
            DnsClient hw = HwDnsUtil.init(cloud);
            ListPublicZonesResponse zonesResp = HwDnsUtil.zones(hw);
            List<PublicZoneResp> domains = zonesResp.getZones();
            domains.forEach(domain -> {
                resp.add(DnsDomain.builder()
                        .cloud(CloudEnums.HUAWEI)
                        .domain(domain.getName())
                        .domainId(domain.getId())
                        .recordCount(Long.valueOf(domain.getRecordNum()))
                        .build());
            });
        } else {
            throw new BusinessException("暂不支持云厂商" + cloud.getCloud().getName());
        }
        return resp;
    }
}
